package 尚硅谷;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;

/**
 * @author zhangmin
 * @create 2022-03-23 14:49
 * AtomicReference---有ABA问题，虽然已经中间从100-101-100的变化了，但最后会会输出true
 */
public class ABADemo {
    static AtomicReference<Integer> atomicReference=new AtomicReference<>(100);//初始设置为100--A
    static AtomicStampedReference<Integer> atomicStampedReference=new AtomicStampedReference<>(100,1); //初始值为100，版本号为1

    public static void main(String[] args) {
        new Thread(()->{
            atomicReference.compareAndSet(100,101);//设置为101---B
            atomicReference.compareAndSet(101,100);//再设置回到100----A
        },"t1").start();

        new Thread(()->{
            try {
                TimeUnit.SECONDS.sleep(1);//保证t1执行完毕
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(atomicReference.compareAndSet(100,2022)+"\t"+atomicReference.get());
        },"t2").start();
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("=========以下时ABA问题的解决=========");
        //t3线程模拟ABA问题
        new Thread(()->{
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName()+"\t 第一次版本号："+stamp);//取得原本的版本号
            //暂停1秒钟
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // 传入4个值，期望值，更新值，期望版本号，更新版本号
            atomicStampedReference.compareAndSet(100,101,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
            System.out.println(Thread.currentThread().getName()+"\t 第二次版本号："+atomicStampedReference.getStamp());
            atomicStampedReference.compareAndSet(101,100,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);
            System.out.println(Thread.currentThread().getName()+"\t 第三次版本号："+atomicStampedReference.getStamp());

        },"t3").start();
        //t4线程用于验证ABA是否可以解决
        new Thread(()->{
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName()+"\t 第一次版本号："+stamp);//也取得原本的版本号
            //暂停3秒钟4线程，保证t3线程完成一次ABA操作
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            boolean res=atomicStampedReference.compareAndSet(100,2022,stamp,stamp+1);
            System.out.println(Thread.currentThread().getName() + "\t 修改成功否：" + res + "\t 当前最新实际版本号：" + atomicStampedReference.getStamp());
            System.out.println(Thread.currentThread().getName() + "\t 当前实际最新值" + atomicStampedReference.getReference());

        },"t4").start();
    }
}
